/**
 * 公共JS库，从v2.x开始不兼容标清，仅适用于高清项目
 * @start 20151201
 * @date 20160325
 * @author lutongnet
 * 
 * -----------------------------------------
 * v2.0.2（20160325）
 * Epg.scrollScreen滚屏增加可选的动画实现；
 * 修改完善滚屏动画几个小问题；
 * 完善Epg.Button相关，具体包括：
 * 增加Epg.Button.config配置参数，方便全局修改；
 * 增加可选的共用光标功能，主要是为了更加流畅的实现光标动画，具体包括所有与shareCursor相关代码；
 * 修复滚屏动画与光标移动动画之间的各种冲突问题；
 * 将滚屏代码移动到common.exta.js中；
 * 
 * 
 * -----------------------------------------
 * v2.0.1（20160315）
 * 增加Epg.scrollScreen滚屏相关方法(common.core.js中)；
 * 完善Epg.autoMakeBtnDir相关方法；
 * 完善Epg.addClass和Epg.removeClass这2个方法；
 * 
 * 
 * -----------------------------------------
 * v2.0.0（20151211）
 * 在common.core_v1.0.19.js基础上修改而来；
 * 删除Epg.Log.updateCalorie()、Epg.Log.gsta();
 * 删除Epg.Button中sliders相关、useJquery相关、以及一些没用的东西；
 * 删除标清的Epg.tip和Epg.ykqTip这2个方法；
 * 删除Epg.Html方法；
 * 删除Epg.slide方法；
 * 删除Epg.ajax方法；
 * 删除Epg.Mp.getPlayTimePercent方法；
 * 删除Epg.fx.setInterval和stopInterval等不常用方法；
 * 删除旧的Epg.marquee方法，改用css3重新实现一个版本；
 * 除了少部分外露方法，大部分都改为闭包写法；
 */


// 以下4个字段正常情况下应该是在com_head.jsp中已经定义好，这里增加一层判断只是为了防止没有定义报错！
if(typeof debug_mode === 'undefined') window.debug_mode = true; // 调试模式，上线后必须把此参数改为false！
if(typeof enable_animate === 'undefined') window.enable_animate = true; // 开启动画
if(typeof is_ott === 'undefined') window.is_ott = false; // 默认不是OTT项目
if(typeof is_sd === 'undefined') window.is_sd = false; // 默认是高清项目


var KEY_BACK 		 = 0x0008;  // 返回/删除

var KEY_ENTER		 = 0x000D;  // 确定

var KEY_PAGE_UP 	 = 0x0021;  // 上页
var KEY_PAGE_DOWN	 = 0x0022;  // 下页
var KEY_LEFT		 = 0x0025;  // 左
var KEY_UP			 = 0x0026;  // 上
var KEY_RIGHT 		 = 0x0027;  // 右
var KEY_DOWN 		 = 0x0028;  // 下
var KEY_0 			 = 0x0030;  // 0
var KEY_1 			 = 0x0031;  // 1
var KEY_2 			 = 0x0032;  // 2
var KEY_3 			 = 0x0033;  // 3
var KEY_4 			 = 0x0034;  // 4
var KEY_5			 = 0x0035;  // 5
var KEY_6 			 = 0x0036;  // 6 
var KEY_7 			 = 0x0037;  // 7
var KEY_8 			 = 0x0038;  // 8
var KEY_9 			 = 0x0039;  // 9



var KEY_VOL_UP		 = 0x0103;  // Vol+，音量加
var KEY_VOL_DOWN 	 = 0x0104;  // Vol-，音量减
var KEY_MUTE 		 = 0x0105;  // Mute，静音
var KEY_TRACK 		 = 0x0106;  // Audio Track，切换音轨
var KEY_PLAY_PAUSE   = 0x0107;  // >||，播放，暂停
var KEY_FAST_FORWARD = 0x0108;  // >> ，快进
var KEY_FAST_REWIND  = 0x0109;  // << ，快退
var KEY_IPTV_EVENT   = 0x0300;  // 虚拟事件按键
var KEY_RED 		 = 0x0113;  // 红色键
var KEY_GREEN		 = 0x0114;  // 绿色键
var KEY_YELLOW		 = 0x0115;  // 黄色键
var KEY_BLUE		 = 0x0116;  // 蓝色键
var KEY_DELETE		 = 0x0118;  // 删除键(中兴盒子)

var EVENT_MEDIA_END  = 'EVENT_MEDIA_END';  //视频播放结束
var EVENT_MEDIA_ERROR= 'EVENT_MEDIA_ERROR';  //视频播放错误
var EVENT_MENU		 = 'EVENT_MENU'; //OTT的菜单虚拟键
var EVENT_HOME		 = 'EVENT_HOME'; //OTT的主页虚拟键


/**
 * 根据ID获取某个元素
 * @param id
 * @returns
 */
function G(id){return document.getElementById(id);}

/**
 * 显示一个元素
 * @param id
 */
function S(id)
{
	var temp = G(id);
	if(temp) temp.style.visibility = 'visible';
}
/**
 * 隐藏一个元素
 * @param id
 */
function H(id)
{
	var temp = G(id);
	if(temp) temp.style.visibility = 'hidden';
}

/**
 * 返回IPTV门户或者来源地址
 */
function goIptvPortal()
{
	window.location.href = Authentication.CTCGetConfig('EPGDomain');
}

// 命名空间
var Epg = 
{
	/** 调用函数 */
	call: function(fn, args)
	{
		if (typeof fn === 'string' && fn) return eval('(' + fn + ')');
		else if(typeof fn === 'function')
		{
			if(!(args instanceof Array))
			{
				//注意，这里千万不要直接：args=[];然后对args操作，因为arguments存放的是args的引用，否则args会无限循环
				var temp = [];
				for(var i=1; i<arguments.length; i++) temp.push(arguments[i]);
				args = temp;
			}
			return fn.apply(window, args);
		}
	},
	/**
	 * 获取上下文路径，形如：/health-sd/
	 * @returns {String}
	 */
	getContextPath: function()
	{
		return '/' + location.href.split('/')[3] + '/';
	},
	getParent: function()
	{
		return window == window.parent ? window.top : window.parent;
	}
};

// 日志相关
Epg.Log = 
{
	ajax: function(url, async)
	{
		var xmlHttp = null;
		if(window.XMLHttpRequest)
			xmlHttp = new XMLHttpRequest();
		else if(window.ActiveXObject)
			xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
		if(xmlHttp)
		{
			xmlHttp.open("GET", url, async);
			xmlHttp.send(null);
			xmlHttp = null;
		}
		else
		{
			var img = document.createElement('img');
			img.src = url;
			img.style.visibility = 'hidden';//图片必须隐藏，update by 20140922
			document.body.appendChild(img);
		}
	},
	/**
	 * 保存访问日志，target和targetType这2个字段有一个为空均不记录日志
	 * @param source 来源页面，必须参数
	 * @param target 当前页面，必须参数
	 * @param targetType 当前页面类型，必须参数
	 * @param elementCode 当前页面元素编码，只有需要的时候才需要传此值
	 * @param addAccessLog 是否添加访问日志，只有addAccessLog为字符串的'false'才不记录日志，其它情况均记录，
	 * 				把这个参数放在这里是为了兼容以前的写法，因为后面4个参数是新加的
	 * @param pageProp 当前页面属性
	 * @param pagePropSrc 来源页面属性
	 * @param sourceType 来源页面类型，几乎用不着，这个参数将来可能废除
	 * @param elementCodeSrc 来源页面元素编码，也几乎用不到，这个参数将来可能废除
	 */
	access: function(source, target, targetType, elementCode, addAccessLog, pageProp, pagePropSrc, sourceType, elementCodeSrc)
	{
		if(target==='' || targetType==='' || addAccessLog==='false')
			return;
		/*var url = Epg.getContextPath()+'com/log.jsp?method=access&source='+source+'&target='+target+'&targetType='+targetType+'&elementCode='+elementCode+'&pageProp='+pageProp+'&pagePropSrc='+pagePropSrc+'&elementCodeSrc='+elementCodeSrc+'&sourceType='+sourceType;
		this.ajax(url, true);*/
		var postData = {
			'userid': Epg.cookie.get('userid'),//用户ID
			'role': Epg.cookie.get('role'),//角色名
			'orderType': Epg.cookie.get('orderType'),//订购类型：free、day、month、year
			'city': Epg.cookie.get('city'),//城市code
			'entry': Epg.cookie.get('entry'),//入口字段，后来增加的
			'carrier': CONFIG.CARRIER,//运营商
			'appVersion': CONFIG.APP_VERSION,//版本
			'platform': Epg.cookie.get('CHANNEL_CODE'),//平台，OTT版本使用channelCode代替
			'integralStrategy': '',//积分策略，垃圾字段
			'cachable': true,//是否使用缓存，默认使用
			'source': source,//来源页面
			'target': target,//目标，即当前页面
			'targetType': targetType,//当前页面类型
			'apkVersion': Epg.cookie.get('APK_VERSION'),//apk版本
			'version': CONFIG.VERSION//epg api版本	
		};
		Epg.postAPI('access/add', postData, function(res) {
			Epg.debug('添加访问日志成功！');
		});
	},
	/** 更新上一次点播日志 */
	updateLastVodLog: function(callback)
	{
		var url = Epg.getContextPath() + 'com/log.jsp?method=updateLastVodLog';
		this.ajax(url,true);//必须同步 否则某些页面无法更新点播日志中的卡路里 不能为false 否则中兴B600盒子获取不了cookie
		if(typeof callback === "function")
			setTimeout(callback, 100);
	},
	/**
	 * 保存游戏访问日志
	 * @param code为游戏关键字
	 * @param level 当前游戏等级
	 * @param isPassed 是否通过当前关
	 */
	saveGameLog:function(code,level,isPassed)
	{
		var url = Epg.getContextPath() + 'com/log.jsp?method=saveGameLog&code='+code+'&level='+level+'&isPassed='+isPassed;
		this.ajax(url,false);//必须同步 否则某些页面无法保存游戏日志
	},
	/**
	 * 使用JS将前端信息输出到后台，add 20140922
	 */
	debug: function(info)
	{
		var url = Epg.getContextPath() + 'com/log.jsp?method=debug&info='+escape(info);
		this.ajax(url, true);
	}
};


/** 自定义按钮对象 */
Epg.Button = Epg.btn =
{
	_buttonStore: {},//存放页面所有按钮对象
	// 所有默认配置，可以通过Epg.Button.init(config)来修改，也可以直接修改此参数
	config:
	{
		defaultButtonId: '', // 默认按钮
		buttons: [], // 按钮数组对象
		imagePath: '', // 默认图片路径
		initKeys: true, // 是否初始化默认6个按键的事件
		eager: false, // 是否提前加载光标图
		clickKeySound: 'defaultClick', //设置默认点击的声音
		moveKeySound: 'defaultMove', //设置默认移动按钮的声音
		shareCursor: false, // 同一个页面所有光标使用同一个div或img来实现，这种情况特别适合于所有光标风格都相同的页面，但不适合页面对话框有带动画的的情况
		shareCursorId: 'default_share_cursor', // 公用光标ID，如需关闭动画，请到common_hd.css中删除对应的transition属性即可
		shareCursorWrapperId: 'wrapper' // 公用光标容器ID，不传或者不存在时用document.body替代
	},
	/**
	 * 初始化按钮
	 * @param defaultButtonId 默认按钮ID，可以是string类型，也可以是string数组
	 * @param buttons 按钮数组
	 * @param imagePath 图片路径，如果焦点图或者默认图不是http开头会自动在前面添加imagePath
	 * @param initKeys boolean类型，是否初始化6个默认按键：上、下、左、右、确定、返回
	 * @param eager 是否提前加载焦点图片，boolean类型
	 * 更多config参数：
	 * clickKeySound：点击的按键声音，不传会有默认值，目前仅支持OTT，传false时表示禁用
	 * moveKeySound：移动按钮的按键声音，不传会有默认值，目前仅支持OTT，传false时表示禁用
	 * animate： 全局的动画开关
	 * animateType：动画实现方式，可选：'js'、'css3'，默认js实现，
	 * 配置在按钮上的可选参数：
	 * disable：如果配置为true，那么将会视作这个按钮不存在，增加此参数可以避免移除DOM或者移除buttons对象的麻烦，add by 20150707
	 * zoom： 是否启用按钮聚焦时放大效果，zoom与animate不能同时开启
	 * zoomScale： 按钮聚焦放大的倍数，默认1.2倍
	 * defaultScale：按钮聚焦还原时的放大倍数，默认1倍，add by 20150617
	 * animate：是否开启光标移动动画效果，只有prev和current都开启了才会有动画效果，可选值：true、false
	 * animateGroup：动画分组，对于设置了分组的按钮，只有属于一个分组里面的按钮之间移动才会有动画效果
	 * twinkle：是否开启按钮闪烁，可以是true或者false，也可以是闪烁的毫秒数，默认200毫秒
	 * autoPrefix：如果图片路径不是http开头是否自动添加imagePath，默认true
	 * focusClass：光标聚焦时添加的样式，会自动添加“btn_focus_”前缀，一般通过这个调整img的border来模拟光标，目前支持“yellow”和“blue”2种颜色的光标，注意focusClass和focusImage二者并不冲突
	 */
	init: function(defaultButtonId, buttons, imagePath, initKeys, eager)
	{
		var config = defaultButtonId;
		if(arguments.length >= 2)
		{
			config =
			{
				defaultButtonId: defaultButtonId,
				buttons: buttons,
				imagePath: imagePath,
				initKeys: initKeys,
				eager: eager
			};
		}
		for(var i in config) this.config[i] = config[i];
		config = this.config;
		
		// 如果启用公用光标，并且不存在，自动创建共用光标，add 20160324
		if(config.shareCursor && !G(config.shareCursorId))
		{
			var wrapper = config.shareCursorWrapperId; // 光标所在的容器
			wrapper = (wrapper ? G(wrapper) : document.body) || document.body;
			var elem = document.createElement('div');
			elem.id = config.shareCursorId;
			wrapper.appendChild(elem);
		}
		
		//如果需要初始化默认的6个按键值
		if(config.initKeys)
		{
			Epg.key.init();
			Epg.key.set(
			{
				KEY_ENTER: 'Epg.Button.click()',			//确定键
				KEY_LEFT: 'Epg.Button.move("left")',		//左键
				KEY_RIGHT: 'Epg.Button.move("right")',		//右键
				KEY_UP: 'Epg.Button.move("up")',			//上键
				KEY_DOWN: 'Epg.Button.move("down")',		//下键
				//KEY_BACK1: 'back()'							//返回键
			});
		}
		
		this.previous = null,
		this._buttonStore = {};
		for(var i=0; i<config.buttons.length; i++)
		{
			var button = config.buttons[i];
			var _button = G(button.id); // DOM 对象
			
			// 主要是为了适配IE7莫名其妙的问题
			if(!button) continue;
			
			// 自动添加样式前缀，add 20160324
			button.focusClass = (button.focusClass && !/^btn_focus_.*$/g.test(button.focusClass) ? 'btn_focus_' : '') + button.focusClass;
			
			// 如果没有设置默认按钮，直接把图片的src用作按钮，要求必须写在window.onload里面，否则部分盒子获取不到src
			if(!button.linkImage && _button) button.linkImage = _button.src;

			//如果(配置了imagePath && 当前按钮配置了焦点图片 && 当前按钮没有配置autoPrefix=false && 焦点图片不是http开头)
			if(config.imagePath && button.focusImage && button.autoPrefix!==false && button.focusImage.indexOf('http')<0)
				button.focusImage = config.imagePath + button.focusImage;
			
			if(config.imagePath && button.linkImage && button.autoPrefix!==false && button.linkImage.indexOf('http')<0)
				button.linkImage = config.imagePath + button.linkImage;
			
			// 如果全局禁用了动画，给每个按钮都禁用动画，update by 20140923
			if(config.animate === false) button.animate = false;
			
			//add by 20150328，增加onclick事件让手机上也能玩
			//update by 20150415，改成仅用于开发时使用，因为华为高清盒子上img添加onclick的话机顶盒会生成自己的一套光标
			if(debug_mode && _button)
			{
				//这种写法会在华为高清上生成2套光标，故不可取
				//_button.setAttribute('onclick', 'Epg.Button.click(undefined, "'+button.id+'")');
				
				//以下写法在天猫OTT盒子上也会形成2套光标，故也注释掉算了，测试需要的时候再自己打开吧，update by 20150717
				var support_mobile = false; //是否支持手机操作，测试时可以设置为true，上线后必须false
				if(support_mobile)
				{
					_button.style.cursor = 'pointer';
					_button.addEventListener('click', function(e){Epg.Button.click(undefined, e.target.id);});
				}
			}
			
			this._buttonStore[button.id] = button;
			 // 提前加载取图片（如果需要）
			if((button.eager || config.eager) && button.focusImage) new Image().src = button.focusImage;
		}
		
		// 设置默认获得焦点的按钮
		if(typeof config.defaultButtonId === 'string') this.current = this.get(config.defaultButtonId);
		else if(config.defaultButtonId instanceof Array)
		{
			for(var i=0, max=config.defaultButtonId.length; i<max; i++)
			{
				var button = this.get(config.defaultButtonId[i]);
				if(button)
				{
					this.current = button;
					break;
				}
			}
		}
		this.update();
	},
	
	/** 获取按钮 */
	get: function(id)
	{
		// id如果不传，默认返回当前按钮
		if(id === undefined) id = this.current.id;
		if(G(id))
		{
			var btn = this._buttonStore[id];
			//如果按钮配置了disable:true，那么视作这个按钮不存在，增加此参数可以避免移除DOM或者移除buttons对象的麻烦，add by 20150707
			if(btn && btn.disable !== true) return this._buttonStore[id];
		}
	},
	
	/** 移动 */
	move: function(dir)
	{
		this._dir = dir;//add by 20150619，临时保存当前移动方向，有时候有获取这个的需要
		Epg.playKeySound(this.config.moveKeySound);//播放按键声音，add by 20150506
		
		//update 20140508 如果当前按钮定义了beforeMove方法并且改方法之后行返回false，那么阻止按钮的本次移动
		if(this.current.beforeMove && Epg.call(this.current.beforeMove, [dir, this.current]) === false) return;
		
		var button;
		var nextButtonId = this.current[dir];
		// update 20140508 如果是字符串，强制改为数组，简化代码
		if(typeof nextButtonId == "string") nextButtonId = [nextButtonId];
		if(nextButtonId instanceof Array)
		{
			for(var i=0; i<nextButtonId.length; i++)
			{
				button = this.get(nextButtonId[i]);
				if(button) break;
			}
			this.previous = this.current;
			if(button)
			{
				this.current = button;
				
				if(button.scrollDir === "x") {
					Epg.scroll.repair();
					this.update();
					Epg.scroll.check(button, dir);
				}else {
					Epg.scrollScreen.repair(); // 修复由于可能的光标移动过快而导致的光标错位问题
					this.update();//只有按钮存在才更新图片，update by 20140924
					Epg.scrollScreen.check(button, dir);
				}
				
				/*Epg.scrollScreen.repair(); // 修复由于可能的光标移动过快而导致的光标错位问题
				this.update();//只有按钮存在才更新图片，update by 20140924
				Epg.scrollScreen.check(button, dir);*/
			}
		}
		//this.update();//只有按钮存在才更新图片，update by 20140924
		Epg.call(this.current.moveHandler, [this.previous, this.current, dir]);
	},
	
	/** 显示设置初始获得焦点的按钮 */
	set: function(buttonId)
	{
		var btn = this.get(buttonId);
		if(!btn) return;//add by 20150707，如果按钮不存在，不作任何处理
		
		this.previous = this.current;
		this.current = btn;
		this.update();
	},
	
	/** 
	 * 点击确定按钮
	 * @param interceptor 点击按钮之前触发一个拦截方法
	 * @param btnId 要触发的按钮ID，默认不传就是单击当前光标所在按钮
	 */
	click: function(interceptor, btnId)
	{
		//update by 20150328，如果传了btnId参数，并且它和当前按钮id不一致，那么就设置这个参数为当前按钮
		//这个主要是为了电脑或者手机上能够用鼠标直接单击
		//if(btnId && btnId !== this.current.id) this.set(btnId);
		//Epg.playKeySound(this.config.clickKeySound);//播放按键声音，add by 20150506

		// 异步统计按钮点击
		//var log = this.current.log;
		//if(log) Epg.Log.access(log.source, log.target, log.targetType);

		Epg.call(interceptor, [this.current]); // 在点击按钮前可以执行一个自定义函数，比如统计按钮点击功能
		Epg.call(this.current.action, [this.current]);
	},
	
	/** 更新 */
	update: function()
	{
		if(this.config.shareCursor) // 如果启用公用光标，add 20160324
		{
			this.updateShareCursor();
			return;
		}
		var prev = this.previous;
		var current = this.current;
		if(prev && G(prev.id))//如果存在上一个按钮
		{
			var _prev = G(prev.id); // DOM 对象
			// add 20150415,如果配置了focusClass，增加border模拟光标的样式
			if(prev.focusClass) Epg.removeClass(_prev, prev.focusClass);
			if(prev.linkImage) _prev.src = prev.linkImage;
			// add by 20140922，增加闪烁功能
			if(prev.twinkle) Epg.twinkle.stop();
			
			if(enable_animate && prev.zoom)// add by 20150331，增加zoom动画
			{
				var parent = _prev.parentNode;
				var defaultScale = prev.defaultScale || 1;//add by 20150617，还原时的比例，默认1
				parent.style.webkitTransition = '';//大小还原时不需要动画，所以需要立即去掉transition属性
				parent.style.transition = '';
				parent.style.webkitTransform = 'scale('+defaultScale+')';//启用zoom动画必须保证父节点是div
				parent.style.transform = 'scale('+defaultScale+')';//启用zoom动画必须保证父节点是div
				parent.style.zIndex = ''; //光标移开时还原默认的zIndex
			}
			Epg.call(prev.blurHandler, [prev]);
		}
		if(current)//如果存在当前按钮
		{
			var _current = G(current.id);
			//add by 20150415,如果配置了focusClass，增加border模拟光标的样式
			if(current.focusClass) Epg.addClass(_current, current.focusClass);
			if(current.focusImage) _current.src = current.focusImage;
			
			//动画代码开始，add by 20140923
			//enable_animate作为一个全局的开关参数，用来控制是否允许执行动画
			//如果有上一个按钮，并且符合执行动画条件
			if(prev && enable_animate!==false && prev.animate && current.animate && prev.animateGroup === current.animateGroup)
			{
				var pImg = G(prev.id);
				var cImg = G(current.id);
				var p = pImg.parentNode;
				var c = cImg.parentNode;
				Epg.Button._zIndex = c.style.zIndex;//存储zIndex用来下次还原
				c.style.zIndex = 300;//移动的时候保证zIndex在最前面
				if(this.config.animateType === 'js')//如果采用js实现动画
				{
					Epg.animate(c, 
					{
						left: [Epg.css(p, 'left'), Epg.css(c, 'left')],
						top: [Epg.css(p, 'top'), Epg.css(c, 'top')]
					}, 'fast', function()
					{
						c.style.zIndex = Epg.Button._zIndex;//还原成之前的zIndex
						Epg.Button._zIndex = undefined;
						// add by 20140922，增加闪烁功能
						if(Epg.btn.current.twinkle) Epg.twinkle.start(Epg.btn.current.id, Epg.btn.current.twinkle);
					});
					//将当前图片的宽高度从prev的状态变成current的状态，如果宽高度都一样那么动画不会执行
					Epg.animate(cImg, 
					{
						width: [Epg.css(pImg, 'width'), Epg.css(cImg, 'width')],
						height: [Epg.css(pImg, 'height'), Epg.css(cImg, 'height')]
					}, 'fast', function(){}, 'default2');//tag一定不能和上面的一样
				}
				else if(this.config.animateType === 'css3')//否则使用css3实现，还有些问题，有待完善，add by 20150603
				{
					var _left = Epg.css(c, 'left'), _top = Epg.css(c, 'top'),
						_width = Epg.css(cImg, 'width'), _height = Epg.css(cImg, 'height');
					Epg.css(c, 'webkitTransition', '');
					Epg.css(c, 'transition', '');
					Epg.css(c, 'left', Epg.css(p, 'left'));
					Epg.css(c, 'top', Epg.css(p, 'top'));
					Epg.css(cImg, 'width', Epg.css(pImg, 'width'));
					Epg.css(cImg, 'height', Epg.css(pImg, 'height'));
					setTimeout(function()
					{
						Epg.css(c, 'webkitTransition', 'all 0.2s');
						Epg.css(c, 'transition', 'all 0.2s');
						Epg.css(c, 'left', _left);
						Epg.css(c, 'top', _top);
						Epg.css(c, 'width', _width);
						Epg.css(c, 'height', _height);
					}, 20);//延迟20ms执行避免一些不必要的问题
					Epg.one(c, 'webkitTransitionEnd mozTransitionEnd MSTransitionEnd otransitionend transitionend', function()
					{
						c.style.zIndex = Epg.Button._zIndex;//还原成之前的zIndex
						Epg.Button._zIndex = undefined;
						if(Epg.btn.current.twinkle) Epg.twinkle.start(Epg.btn.current.id, Epg.btn.current.twinkle);
					});
				}
			}
			else
			{
				// add by 20140922，增加闪烁功能
				if(current.twinkle) Epg.twinkle.start(current.id, current.twinkle);
				if(enable_animate && current.zoom)// add by 20150331，增加zoom动画
				{
					var parent = G(current.id).parentNode;
					var zoomScale = current.zoomScale || 1.2;//放大比例，默认1.2倍
					parent.style.zIndex = '300'; //启用zoom动画的按钮必须保证z-index在最前，否则可能会被其它图片遮住
					parent.style.webkitTransition = 'all 0.5s';
					parent.style.transition = 'all 0.5s';
					parent.style.webkitTransform = 'scale('+zoomScale+')';//启用zoom动画必须保证父节点是div
					parent.style.transform = 'scale('+zoomScale+')';//启用zoom动画必须保证父节点是div
				}
			}
			Epg.call(current.focusHandler, [current]);
		}
	},
	/**
	 * 当启用公用光标时，使用本方法更新光标，会忽略一切杂七杂八的属性，如闪烁、动画，等等，add 20160324<br>
	 * 可以针对具体按钮设置 shareCursor:false 来单独禁用某个按钮上的此功能<br>
	 */
	updateShareCursor: function()
	{
		var prev = this.previous;
		var current = this.current;
		var cursor = G(this.config.shareCursorId);
		if(!cursor) return;
		if(prev)//如果存在上一个按钮
		{
			var p = G(prev.id);
			if(!p) return;
			if(prev.shareCursor === false) // 如果上一个按钮没有启用公用光标
			{
				if(prev.linkImage) p.src = prev.linkImage;
				if(prev.focusClass) Epg.removeClass(p, prev.focusClass);
			}
			else
			{
				if(prev.linkImage) cursor.src = prev.linkImage;
			}
			Epg.call(prev.blurHandler, [prev]);
		}
		if(current)
		{
			var c = G(current.id);
			if(!c) return;
			if(current.shareCursor === false) // 如果上一个按钮没有启用公用光标
			{
				if(prev && prev.focusClass) Epg.removeClass(cursor, prev.focusClass); // 无论如何先把共用光标的样式去掉
				if(current.focusImage) c.src = current.focusImage;
				if(current.focusClass) Epg.addClass(c, current.focusClass);
			}
			else
			{
				if(current.focusImage) cursor.src = current.focusImage;
				var className = cursor.className;
				if((!prev || prev.shareCursor === false) && current.focusClass) Epg.addClass(cursor, current.focusClass);
				else if(prev && current.focusClass && prev.focusClass !== current.focusClass)
				{
					var reg = new RegExp('(^|\\s)'+(prev.focusClass||'')+'(\\s|$)', 'g');
					cursor.className = className.replace(reg, current.focusClass);
				}
				// var position = Epg.getAbsolutePosition(c); // 这种方法获取的坐标会忽略border的宽度，所有不是很准
				var position = c.getBoundingClientRect(); // 用这种方法虽然比较准，但是会忽略滚动值，所以获取top时要加上scrollTop的值
				cursor.style.left = position.left + 'px';
				cursor.style.top = position.top + Epg.scrollScreen.config.scrollTop + 'px';
				cursor.style.width = position.width + 'px';
				cursor.style.height = position.height + 'px';
				// 没有上一个按钮，表示是页面第一次初始化按钮，添加transition动画，
				// 一来是为了让动画可以由JS来控制，二来是解决部分盒子第一次聚焦光标也有动画的问题
				if(!prev && enable_animate)
				{
					setTimeout(function()
					{
						cursor.style.webkitTransition = 'all 0.3s';
						cursor.style.transition = 'all 0.3s';
					}, 200); // 部分盒子不延迟执行的话，页面第一次聚焦光标仍然会有动画
				}
			}
			Epg.call(current.focusHandler, [current]);
		}
	}
};

/** 播放器实例，OTT版时浏览器会注入一个叫mp的对象，不过跟这个并不冲突 */
var mp;

/** 播放器相关代码 */
Epg.Mp = Epg.mp = 
{
	speed : 1,			// 正常播放速度
	state : 'play', 	// play-播放,pause-暂停,fastForward-快进,fastRewind-快退
	muteFlag : 0,		// 0-有声,1-静音
	live: false,		// 直播
	defaultTip: false,  // 是否开启默认的提示文字， add 20140514
	
	/** 初始化播放器 */
	init: function(defaultTip)
	{
		this.defaultTip = defaultTip;//add 20140514
		if(!is_ott)//OTT版不需要这段代码
		{
			mp = new MediaPlayer();
			var instanceId 			= mp.getNativePlayerInstanceID();
			var playListFlag 		= 0;
			var videoDisplayMode 	= 1;		// 0-自定义尺寸,1-全屏(默认),255-不显示在背后播放
			var height 				= 100;
			var width 				= 100;
			var left 				= 50;		// 自定义尺寸必须指定
			var top		 			= 50;		// 自定义尺寸必须指定
			var muteFlag 			= 0;		// 0-有声(默认),1-静音
			var useNativeUIFlag 	= 1;		// 0-不使用player的本地UI显示功能,1-使用player的本地UI显示功能(默认)
			var subtitleFlag 		= 0;		// 0-不显示字幕(默认),1-显示字幕
			var videoAlpha 			= 0;		// 0-不透明(默认),100-完全透明
			var cycleFlag 			= 1;		// 0-设置为循环播放（默认值）, 1-设置为单次播放 
			var randomFlag 			= 0;
			var autoDelFlag 		= 0;
			mp.initMediaPlayer(instanceId,playListFlag,videoDisplayMode,height,width,left,top,muteFlag,useNativeUIFlag,subtitleFlag,videoAlpha,cycleFlag,randomFlag,autoDelFlag);
			mp.setAllowTrickmodeFlag(0); //0-允许 TrickMode 操做 ,1-不允许 TrickMode 操作 (默认值)
		}
		mp.setProgressBarUIFlag(0); //0：不显示自带的进度条，1：显示自带进度条，默认为显示
		mp.setAudioVolumeUIFlag(1); //显示自带的音量UI，我们自定义的声音UI有些机顶盒响应不了
	},
	
	/** 暂停 */
	pause: function(callback)
	{
		this.speed = 1;
		this.state = 'pause';
		//if(this.defaultTip) Epg.ykqTip("暂停");
		//try一下的目的是为了电脑上不报错
		try{mp.pause();}catch(e){}
		Epg.call(callback, [this]);
	},
	
	/** 从暂停、快进、快退中恢复 */
	resume: function(callback)
	{
		this.speed = 1;
		this.state = 'play';
		//if(this.defaultTip) Epg.ykqTip("播放");
		//try一下的目的是为了电脑上不报错
		try{mp.resume();}catch(e){}
		Epg.call(callback, [this]);
	},
	
	/** 播放或暂停 */
	playOrPause: function(callback)
	{
		if(this.state=='play')
			this.pause();
		else
			this.resume();
		Epg.call(callback, [this.state, this]);
	},
	
	/** 快进 */
	fastForward: function(callback)
	{
		if(this.speed >= 32 || this.state == 'fastRewind')
			this.resume();
		else
		{
			this.speed = this.speed * 2;
			this.state = 'fastForward';
			if(this.defaultTip)
				Epg.ykqTip('快进：x'+this.speed);
			mp.fastForward(this.speed);
		}
		Epg.call(callback, [this.state, this.speed, this]);
	},
	
	/** 快退 */
	fastRewind: function(callback)
	{
		if(this.speed >= 32 || this.state == 'fastForward')
		{
			this.resume();
		}
		else
		{
			this.speed = this.speed * 2;
			this.state = 'fastRewind';
			if(this.defaultTip)
				Epg.ykqTip('快退：x'+this.speed);
			mp.fastRewind(-this.speed);
		}
		Epg.call(callback, [this.state, this.speed, this]);
	},
	
	/** 调大声音 */
	volUp: function(callback)
	{
		var volume = (+mp.getVolume());
		if(is_ott)
		{
			var temp = 5 - (volume % 5);//这样做的目的是为了保证以后每次递增时都是5的倍数
			volume = volume + temp;//ott的最大声音不固定，所以无需做最大判断，一般是150
		}
		else
		{
			volume += 5;
			volume = volume > 100 ? 100 : volume;
		}
		if(this.defaultTip)
		{
			Epg.ykqTip('音量：'+volume);
		}
		mp.setVolume(volume);
		Epg.call(callback, [volume,this]);
	},
	
	/** 调小声音 */
	volDown: function(callback)
	{
		var volume = (+mp.getVolume());
		if(is_ott)
		{
			var temp = volume % 5;
			temp = temp === 0 ? 5 : temp;//这样做的目的是为了保证以后每次递增时都是5的倍数
			volume = volume - temp;
		}
		else
		{
			volume -= 5;
			volume = volume < 5 ? 0 : volume;
		}
		if(this.defaultTip)
		{
			Epg.ykqTip('音量：'+volume);
		}
		mp.setVolume(volume);
		Epg.call(callback, [volume,this]);
	},
	
	/** 切换声道 */
	switchAudioChannel: function(callback)
	{
		mp.switchAudioChannel();
		Epg.call(callback, [this.getCurrentAudioChannel(), this]);
	},
	
	/** 获取当前声道 */
	getCurrentAudioChannel: function()
	{
		if(!mp) return 'Stereo';
		return mp.getCurrentAudioChannel() || 'Stereo';
	},
	
	/** 开启或关闭声音 */
	toggleMuteFlag: function(callback)
	{
		++this.muteFlag;
		if(this.defaultTip)
			Epg.ykqTip(this.muteFlag%2==0?'关闭':'开启'+'静音');
		mp.setMuteFlag(this.muteFlag%2);
		Epg.call(callback, [this.muteFlag%2, this]);
	},
	
	/** 获取播放串 */
	getMediaStr: function(url)
	{
		var json = '';
		json += '[{mediaUrl:"'+url+'",';
		json +=	'mediaCode: "jsoncode1",';
		json +=	'mediaType:2,';
		json +=	'audioType:1,';
		json +=	'videoType:1,';
		json +=	'streamType:1,';
		json +=	'drmType:1,';
		json +=	'fingerPrint:0,';
		json +=	'copyProtection:1,';
		json +=	'allowTrickmode:1,';
		json +=	'startTime:0,';
		json +=	'endTime:20000.3,';
		json +=	'entryID:"jsonentry1"}]';
		return json;
	},
	
	/** 
	 * 全屏播放<br>
	 * 针对OTT：<br>
	 * 1、播放MP3：fullscreenPlay('xxx.mp3')<br>
	 * 2、播放传统视频：fullscreenPlay('xxx.mp4')<br>
	 * 3、播放混合音视频：fullscreenPlay('xxx.mp3', 'xxx.mp4')<br>
	 */
	fullscreenPlay: function(url)
	{
		url = url.replace("baidu.com","guoguo-cdn.lutongnet.com");
		if( is_ott )
		{
			if(arguments.length === 2)
			{
				var audioUrl = arguments[0];
				var videoUrl = arguments[1];
				mp.initMixMediaPlayer(audioUrl, videoUrl);
			}
			else
			{
				var type = (url && /\.(mp3|aac)$/g.test(url))?0:1;//0表示播放MP3，1表示播放视频，不传默认也是播放视频
				mp.initMediaPlayer(url, type);
			}
		}
		else
		{
			mp.setSingleMedia(this.getMediaStr(url));
			mp.setVideoDisplayMode(1);
			mp.refreshVideoDisplay();
		}
		mp.playFromStart();
	},
	
	/** 小视频播放 */
	smallvodPlay: function(url, left, top, width, height)
	{
		url = url.replace("baidu.com","guoguo-cdn.lutongnet.com");
		if( is_ott )
		{
			if(url && /\.mp3$/g.test(url))//0表示播放MP3，1表示播放视频，不传默认也是播放视频
				mp.initMediaPlayer(url, 0);
			else
				mp.initMediaPlayer(url, left, top, width, height);
		}
		else
		{
			mp.setSingleMedia(this.getMediaStr(url));
			mp.setVideoDisplayMode(0);
			mp.setVideoDisplayArea(left, top, width, height);
			mp.refreshVideoDisplay();
		}
		mp.playFromStart();
	},
	
	/** 全屏直播 */
	liveFullscreenPlay: function(channelID)
	{
		this.live = true;
		mp.joinChannel(channelID);
		mp.setVideoDisplayMode(1);
		mp.refreshVideoDisplay();
		mp.play();
	},
	
	/** 小视频直播 */
	liveSmallvodPlay: function(channelID, left, top, width, height)
	{
		this.live = true;
		mp.joinChannel(channelID);
		mp.setVideoDisplayMode(0);
		mp.setVideoDisplayArea(left, top, width, height);
		mp.refreshVideoDisplay();
		mp.play();
	},
	
	/** 定点播放 */
	playByTime: function(second)
	{
		mp.playByTime(1, second);
	},
	
	/** 获取当前播放时间，add by 20150606 */
	getCurrentPlayTime: function()
	{
		if(mp) return (mp.getCurrentPlayTime() || 0);
		else return 0;
	},
	
	/** 获取总时长，add by 20150606 */
	getMediaDuration: function()
	{
		if(mp) return (mp.getMediaDuration() || 0);//还没加载时一般获取到的是NaN或者0
		else return 0;
	},
	
	/** 将时间转换成MM:SS形式，add by 20150606 */
	parseTimeInfo: function(second)
	{
		var m = Math.floor(second / 60);
		m = m < 10 ? ( '0' + m ) : m;
		var s = second % 60;
		s = s < 10 ? ( '0' + s ) : s;
		return m + ':' + s;
	},
	
	/** 返回MM:SS/MM:SS 形式的时间 */
	getPlayTimeInfo: function()
	{
		return this.parseTimeInfo(this.getCurrentPlayTime())+'/' + this.parseTimeInfo(this.getMediaDuration());
	},
	
	/** 获取播放总进度比例，返回介于0-1之间的小数 */
	getRate: function()
	{
		var duration = this.getMediaDuration();
		if(duration === 0) return 0;//因为0/0=NaN，所以要避免这种情况
		return this.getCurrentPlayTime()/duration;
	},
	
	/** 停止播放，释放资源 */
	destroy: function()
	{
		if(this.live)
		{
			this.live = false;
			mp.leaveChannel();
		}
		if(mp)
			mp.stop();
	},
	
	/** 是否播放完了或播放出错 */
	isEndOrError: function(keyCode)
	{
		return keyCode === 'EVENT_MEDIA_END' || keyCode === 'EVENT_MEDIA_ERROR';
	}
};
popup = function() {
	var self = {};

	/* 调用方法
	 amGloble.dg.popup.pop({
	 content: '请选择至少一份',
	 style: 'background-color:rgba(0,0,0,0.5);color:#fff;border:none;',
	 time: 1
	 });
	 */

	self.pop = function(opt) {
		var opt0 = {};
		// 默认按钮
		if (opt) {
			opt0.title = opt.title || null;
			opt0.content = opt.content || '';
			opt0.time = opt.time || opt.duration || 2;
			//opt0.time = 200000;
			opt0.style = opt.style || 'background-color:rgba(0,0,0,0.5);color:#fff;border:none;font-size:0.3rem;line-height:0.3rem;padding:0.3rem;';
			opt0.btn = opt.btn || null;
		}
		layer.open(opt0);
	};

	return self;
}();

(function(document)
{
	/** 事件处理 */
	var event_handler = function(e)
	{

		e = e || window.event;
		var keyCode = e.which || e.keyCode
		if(keyCode === KEY_IPTV_EVENT)
		{
			eval('oEvent = ' + Utility.getEvent());
			Epg.eventHandler(oEvent.type, true);
		}
		else
		{
			//  “返回键后退”功能，add by 20140717
			if(keyCode === KEY_BACK) e.preventDefault();
			Epg.eventHandler(keyCode);
		}
	};

	//根据UA判断onkeydown和onkeypress
	//IPTV上一些比较烂的盒子只支持onkeypress，onkeydown无法响应上下左右（如华为EC2108）,
	//但是电脑上Chrome和IE均只支持onkeydown，火狐则二者都支持，
	//但是现在OTT盒子因为基本上都是webkit内核的，故也只有onkeydown能正常响应上下左右，
	//所以终级解决方案是：开发时统一onkeydown，上线后，IPTV统一使用onkeypress，OTT统一使用onkeydown，update by 20150520
	//if( is_ott || ( debug_mode && /webkit/g.test(navigator.userAgent.toLowerCase()) ) )
	//	document.onkeydown = event_handler;
	//else
	//	document.onkeypress = event_handler;

	window.document.onkeydown = event_handler;

	//window.document.onkeypress = event_handler;
	//window.document.onsystemevent = event_handler;
	//window.document.onkeypress = event_handler;
	//window.document.onirkeypress = event_handler;

})(document);

window.epg = Epg;